#include "globalData.h"

#define TERMINAL_DIFF_WEIGHT 100
#define WIN_WEIGHT 1000000
#define NUM_FEATURES 22

#define ROW 0
#define COL 1
#define NDG 2
#define PDG 3
#define MAX_LINE_TYPE 4

/* we only have 92 stages of the game - from when there are 5 to 96 pieces */
#define NUM_STAGES 92

/* the weight for each feature */
struct Weights
{
    float disc_feature[15];
    float mobility;
    float frontier;
    float disc_diff;
    float stability;
    float player;
    float edge_stab;
    float flippable;
};

/* the value for each feature */
struct Feature_Values
{
    int disc_feature[15];
    int mobility;
    int frontier;
    int disc_diff;
    int stability;
    int player;
    int edge_stab;
    int flippable;
};

/* weights for different stages */
extern Weights WEIGHTS[NUM_STAGES];

/* evaluate the gameState
   #in#  gs             ... current gameState
   #in#  blocked        ... map for the blocked squares
   #in#  player         ... current player
   #ret#                ... integer value of the gameState,
                            positive means favouring WHITE                  */
int evaluateGame(gameState gs, BitBoard blocked, BoardState player, int stage);

/* evaluate a terminal state */
int evaluateTerminal(gameState gs);


/* evaluate the gameState using pre-computed feature values */
float evaluateGameL(Feature_Values v, Weights w);

/* get the value of each feature */
Feature_Values GetFeatureValue(gameState gs, BoardState player, BitBoard blocked);

/* evaluate the given player's number of moves
   #in#  gs             ... current gameState
   #in#  player         ... current player
   #in#  bloked         ... map for the blocked squares
   #ret#                ... number of moves the player has                  */
int evaluateMobility(gameState gs, BoardState player, BitBoard blocked, int & flippable);


/* count the number of frontier discs (discs next to empty squares)
   #in#  self           ... bitboard for the color we are evaluating
   #in#  empty          ... bitboard of empty squares
   #ret#                ... number of frontier discs                        */
int evaluateFrontier(BitBoard self, BitBoard empty);

/* evaluate difference between number of stable discs
   #in#  gs             ... current gameState
   #in#  blocked        ... map for the blocked squares
   #out# edge_stab      ... difference between stable pieces on the edge
   #ret#                ... white_stable - black_stable                     */
int evaluateStabilityDiff(gameState gs, BitBoard blocked, int & edge_stab);

/* calculate the how many more pieces white has over black */
int evaluatePieceDiff(gameState gs);

/* initialise weights by reading from a file
   set up memory used to store the game information                         */
void initialiseEvaluator();

/* initialise board specific information e.g. stability masks affected by
   position of the blocks                                                   */
void initialiseBoardSpecific(BitBoard blocked);

/* write weights back into file */
void WriteWeights(const char * file = NULL);

/* read weights from file */
bool ReadWeights(Weights weight[], const char * file);

/* set weight and get weight functions */
void SetWeights(Weights in_weights[]);
void GetWeights(Weights out_weights[]);


Weights operator-(Weights w1, Weights w2);
Weights operator+(Weights w1, Weights w2);
Weights operator*(float c, Weights w1);
